/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package x10.interfaces.cm15a.receive;

import java.util.BitSet;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import x10.enums.House;
import x10.enums.Interfaces;
import x10.event.X10Command;
import x10.event.X10Event;
import x10.event.X10InterfaceStatus;
import x10.utilities.BitSetUtils;
import x10.utilities.ChunkOfBytes;
import x10.utilities.Utils;

/**
 *
 * @author Denny
 */
public class IFResponseStatus extends X10DeviceReceiver {
    ChunkOfBytes bytes = new ChunkOfBytes();
    private int batteryTimerHighByte = 0;
    private int batteryTimerLowByte = 1;
    private int secondsByte = 2;
    private int minutesByte = 3;
    private int hoursByte = 4;
    private int julianByteHigh = 5;            //Julian Day -- 1 - 365 (or 366)
    private int julianByteLow = 6;
    private int dayMaskByte = 6;
    private int monitoredHouseCodeByte = 7;//Low nibble
    private int firmwareByte = 7;          //High nibble
//    private int monitoredDevicesHighByte = 8;
//    private int monitoredDevicesLowByte = 9;
//    private int monitoredDevicesOnOffStatusHighByte = 10;
//    private int monitoredDevicesOnOffStatusLowByte = 11;
//    private int monitoredDevicesDimStatusHighByte = 12;
//    private int monitoredDevicesDimStatusLowByte = 13;
//    private int ???Byte = 14;    //Unknown - possibly used for macros
//    private int ???Byte = 15;

    public IFResponseStatus(LastAddressedTracker lat, Interfaces interfaceType){
        super(lat, interfaceType);
    }

    public X10Event process(ChunkOfBytes bytes){
        this.bytes = bytes;

        X10InterfaceStatus status = new X10InterfaceStatus();

        status.setFirmwareRevision(getFirmwareRevision());
        status.setInterfaceType(interfaceType);
        status.setMonitoredHouseCode(getMonitoredHouseCode());
        status.setMonitoredDevices(getMonitoredDevices());
        status.setTimeBattery(getTimeBattery());
        status.setTimeInterface(getTimeInterface());
        status.setSource(Interfaces.CM15A.toString());

        return status;
    }

    private House getMonitoredHouseCode(){
        byte temp = bytes.getBytes()[monitoredHouseCodeByte];
        byte code = BitSetUtils.getNibble(temp, "LOWER", "LOWER");
        return House.getHouseFromPowerline(code);
    }

    private int getTimeBattery(){
        byte high = bytes.getBytes()[batteryTimerHighByte];
        byte low = bytes.getBytes()[batteryTimerLowByte];
        return Utils.getIntFromTwoBytes(high, low);
    }

    private long getTimeInterface(){
        GregorianCalendar time = getCalendar();
        time.add(Calendar.DAY_OF_YEAR, getDayOfYear());
        time.add(Calendar.HOUR, getHours());
        time.add(Calendar.MINUTE, getMinutes());
        time.add(Calendar.SECOND, getSeconds());

        //Not used, but testing
//        String day = getDayOfWeek();

        return time.getTimeInMillis();
    }



    private int getFirmwareRevision(){
        byte temp = bytes.getBytes()[firmwareByte];
        byte firmware = BitSetUtils.getNibble(temp, "UPPER", "LOWER");
        return 1 + (int)firmware;
    }

    private HashMap<Integer, X10Command> getMonitoredDevices(){
        HashMap<Integer, X10Command> devices = new HashMap<Integer, X10Command>();

        return devices;
    }

    private GregorianCalendar getCalendar(){
        //Return a calendar with current year set, but nothing else
        GregorianCalendar now = new GregorianCalendar();
        int year = now.get(Calendar.YEAR);
        now.clear();
        now.set(Calendar.YEAR, year);
        //System.out.println("Calendar returned: " + now.toString());
        return now;
    }

    private int getDayOfYear(){
        byte[] julianBytes = new byte[2];
        julianBytes[0] = bytes.getBytes()[julianByteHigh];
        julianBytes[1] = bytes.getBytes()[julianByteLow];

        BitSet bits = BitSetUtils.bytesToBitSet(julianBytes);

        //Get value of first 9 bits, assuming Big Endian
        return BitSetUtils.bitSetToInt(bits, 9);
    }

    private int getHours(){
        int hours = (int)bytes.getBytes()[hoursByte];
        return 2 * (hours + 1);
    }

    private int getMinutes(){
        return (int)bytes.getBytes()[minutesByte];
    }

    private int getSeconds(){
        return (int)bytes.getBytes()[secondsByte];
    }

    @SuppressWarnings("unused")
    private String getDayOfWeek(){
        String ret = null;
        BitSet bits = BitSetUtils.byteToBitSet(bytes.getBytes()[dayMaskByte]);
        if(bits.get(1)){
            ret = "SUNDAY";
        } else if (bits.get(2)){
            ret = "MONDAY";
        } else if (bits.get(3)){
            ret = "TUESDAY";
        } else if (bits.get(4)){
            ret = "WEDNESDAY";
        } else if (bits.get(5)){
            ret = "THURSDAY";
        } else if (bits.get(6)){
            ret = "FRIDAY";
        } else if (bits.get(7)){
            ret = "SATURDAY";
        }
        System.out.println("Day of Week: " + ret);
        return ret;
    }
}
